//
// 队列管理
// Created by kenny on 25-10-30.
//
#include "mcp_queue.h"
#include "mcp_logger.h"
#include <stdlib.h>
#include <string.h>

#ifdef _WIN32
    #include <windows.h>
#else
    #include <pthread.h>
    #include <unistd.h>
#endif

// mcp_queue.c 修改实现
struct mcp_queue_t {
    void* data;
    int front;
    int rear;
    int count;
    int capacity;
    size_t element_size;
    element_copy_func copy_func;  // 拷贝函数
    element_free_func free_func;  // 释放函数
#ifdef _WIN32
    CRITICAL_SECTION lock;
#else
    pthread_mutex_t lock;
#endif
};

/**
 * 创建队列
 * @param capacity
 * @param element_size
 * @param copy_func
 * @param free_func
 * @return
 */
mcp_queue_t* mcp_queue_create(int capacity, size_t element_size,
                                    element_copy_func copy_func,
                                    element_free_func free_func) {
    if (capacity <= 0 || element_size == 0) {
        LOG_ERROR("Invalid queue capacity: %d or element size: %zu", capacity, element_size);
        return NULL;
    }

    mcp_queue_t* queue = (mcp_queue_t*)malloc(sizeof(mcp_queue_t));
    if (!queue) {
        LOG_ERROR("Failed to allocate memory for packet queue");
        return NULL;
    }

    queue->data = malloc(element_size * capacity);
    if (!queue->data) {
        LOG_ERROR("Failed to allocate memory for data array");
        free(queue);
        return NULL;
    }
    queue->element_size = element_size;
    queue->copy_func = copy_func;
    queue->free_func = free_func;

    queue->front = 0;
    queue->rear = 0;
    queue->count = 0;
    queue->capacity = capacity;
    queue->element_size = element_size;

#ifdef _WIN32
    InitializeCriticalSection(&queue->lock);
#else
    if (pthread_mutex_init(&queue->lock, NULL) != 0) {
        LOG_ERROR("Failed to initialize mutex");
        free(queue->data);
        free(queue);
        return NULL;
    }
#endif

    LOG_DEBUG("Generic queue created with capacity: %d, element size: %zu",
              capacity, element_size);
    return queue;
}

/**
 * 销毁队列
 */
void mcp_queue_destroy(mcp_queue_t* queue) {
    if (!queue) {
        return;
    }

    // 清空队列（不释放元素内容，由调用方管理）
    mcp_queue_clear(queue);

    // 释放内存
    free(queue->data);

#ifdef _WIN32
    DeleteCriticalSection(&queue->lock);
#else
    pthread_mutex_destroy(&queue->lock);
#endif

    free(queue);
    LOG_DEBUG("Generic queue destroyed");
}

/**
 * 向队列添加元素
 */
int mcp_queue_enqueue(mcp_queue_t* queue, const void* element) {
    if (!queue || !element) {
        LOG_ERROR("Invalid queue or element pointer");
        return -1;
    }

#ifdef _WIN32
    EnterCriticalSection(&queue->lock);
#else
    pthread_mutex_lock(&queue->lock);
#endif

    // 检查队列是否已满
    if (queue->count >= queue->capacity) {
        LOG_WARN("Queue is full, dropping element");
#ifdef _WIN32
        LeaveCriticalSection(&queue->lock);
#else
        pthread_mutex_unlock(&queue->lock);
#endif
        return -1;
    }

    // 计算目标位置并复制数据
    char* data_ptr = (char*)queue->data;
    void* dest = data_ptr + (queue->rear * queue->element_size);
    // memcpy(dest, element, queue->element_size);
    // 使用拷贝函数或默认memcpy
    if (queue->copy_func) {
        queue->copy_func(dest, element, queue->element_size);
    } else {
        memcpy(dest, element, queue->element_size);
    }

    // 更新队列指针
    queue->rear = (queue->rear + 1) % queue->capacity;
    queue->count++;

    LOG_DEBUG("Element enqueued, queue count: %d/%d", queue->count, queue->capacity);

#ifdef _WIN32
    LeaveCriticalSection(&queue->lock);
#else
    pthread_mutex_unlock(&queue->lock);
#endif

    return 0;
}

/**
 * 从队列取出元素
 */
int mcp_queue_dequeue(mcp_queue_t* queue, void* element) {
    if (!queue || !element) {
        return -1;
    }

#ifdef _WIN32
    EnterCriticalSection(&queue->lock);
#else
    pthread_mutex_lock(&queue->lock);
#endif

    if (queue->count == 0) {
#ifdef _WIN32
        LeaveCriticalSection(&queue->lock);
#else
        pthread_mutex_unlock(&queue->lock);
#endif
        return -1;
    }

    // 取出队首元素
    char* data_ptr = (char*)queue->data;
    void* src = data_ptr + (queue->front * queue->element_size);
    memcpy(element, src, queue->element_size);

    // 更新队列指针
    queue->front = (queue->front + 1) % queue->capacity;
    queue->count--;

#ifdef _WIN32
    LeaveCriticalSection(&queue->lock);
#else
    pthread_mutex_unlock(&queue->lock);
#endif

    return 0;
}

/**
 * 获取队列当前大小
 */
int mcp_queue_size(const mcp_queue_t* queue) {
    if (!queue) {
        return 0;
    }
    return queue->count;
}

/**
 * 检查队列是否为空
 */
int mcp_queue_is_empty(const mcp_queue_t* queue) {
    if (!queue) {
        return 1;
    }
    return (queue->count == 0);
}

/**
 * 检查队列是否已满
 */
int mcp_queue_is_full(const mcp_queue_t* queue) {
    if (!queue) {
        return 0;
    }
    return (queue->count >= queue->capacity);
}

/**
 * 清空队列
 */
void mcp_queue_clear(mcp_queue_t* queue) {
    if (!queue) {
        return;
    }

#ifdef _WIN32
    EnterCriticalSection(&queue->lock);
#else
    pthread_mutex_lock(&queue->lock);
#endif

    // 使用队列注册的释放函数
    if (queue->free_func) {
        for (int i = 0; i < queue->count; i++) {
            int index = (queue->front + i) % queue->capacity;
            char* data_ptr = (char*)queue->data;
            void* element = data_ptr + (index * queue->element_size);
            queue->free_func(element);
        }
    }

    queue->front = 0;
    queue->rear = 0;
    queue->count = 0;

#ifdef _WIN32
    LeaveCriticalSection(&queue->lock);
#else
    pthread_mutex_unlock(&queue->lock);
#endif

    LOG_DEBUG("Queue cleared");
}